package com.wangwei.modules.utils.method;

import java.lang.reflect.Method;

import com.wangwei.modules.utils.method.bean.MethodInfoVO;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.bytecode.CodeAttribute;
import javassist.bytecode.LocalVariableAttribute;
import javassist.bytecode.MethodInfo;

public class MethodUtil {

    /**
     * 获取参数名称
     * @param className
     * @param methodName
     * @return
     */
    public static MethodInfoVO getMethodParamNames(Method method) {
        MethodInfoVO methodInfoVO = new MethodInfoVO(method);
        ClassPool pool = ClassPool.getDefault();
        try {

            CtClass ctClass = pool.get(method.getDeclaringClass().getName());

            CtMethod[] ctMethods = ctClass.getDeclaredMethods();
            CtMethod myMethod = null;
            for (CtMethod ctMethod : ctMethods) {
                boolean equal = true;//方法相同
                if (!ctMethod.getName().equals(method.getName())) {
                    equal = false;//方法名不同
                    continue;
                }
                CtClass[] ptC = ctMethod.getParameterTypes();
                Class<?>[] ptR = method.getParameterTypes();
                if (ptC.length != ptR.length) {
                    equal = false;//参数数量不同
                    continue;
                }
                for (int i = 0; i < ptC.length; i++) {
                    if (!ptC[i].getName().equals(ptR[i].getName())) {
                        equal = false;//参数类型不同
                        break;
                    }
                }
                if (equal) {
                    myMethod = ctMethod;
                    break;
                }

            }

            // 使用javassist的反射方法的参数名
            MethodInfo methodInfo = myMethod.getMethodInfo();
            CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
            LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
            int pos =0;
            // 非静态的成员函数的第一个参数是this
            while (true) {
                if ("this".equals( attr.variableName( pos++))) {
                    break;
                }                
            }
            
            if (attr != null) {
                CtClass[] ts = myMethod.getParameterTypes();
                int len = ts.length;

                for (int i = 0; i < len; i++) {
                    methodInfoVO.addParas(ts[i].getName(), attr.variableName(i + pos));
                }
            }
        } catch (NotFoundException e) {
            e.printStackTrace();
        }
        return methodInfoVO;
    }
}
